package utils

import (
	"fmt"
	"strings"
	"time"
)

const (
	TIME_PRECISION_SECOND      = iota // 定义秒精度常量
	TIME_PRECISION_MILLISECOND = iota // 定义毫秒精度常量
	TIME_PRECISION_MICROSECOND = iota // 定义微秒精度常量
	TIME_PRECISION_NANOSECOND  = iota // 定义纳秒精度常量
)

// NowTimeSecond
// 获取当前时间，格式为：2006-01-02 15:04:05
func NowTimeSecond() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

// NowTimeMillisecond
// 获取当前时间，格式为：2006-01-02 15:04:05.0000
func NowTimeMillisecond() string {
	return time.Now().Format("2006-01-02 15:04:05.0000")
}

// TimeToTimestamp
// 根据指定的精度将 time.Time 转换为时间戳
func TimeToTimestamp(t time.Time, precision int) int64 {
	switch precision {
	case TIME_PRECISION_SECOND:
		return t.Unix()
	case TIME_PRECISION_MILLISECOND:
		return t.UnixMilli() // Go 1.17及以上版本
	case TIME_PRECISION_MICROSECOND:
		return t.UnixMicro() // Go 1.17及以上版本
	case TIME_PRECISION_NANOSECOND:
		return t.UnixNano()
	default:
		fmt.Println("未知的精度，返回秒级时间戳")
		return t.Unix()
	}
}

// TimestampToTime
// 根据指定的精度将时间戳转换回 time.Time
func TimestampToTime(ts int64, precision int) time.Time {
	switch precision {
	case TIME_PRECISION_SECOND:
		return time.Unix(ts, 0).UTC()
	case TIME_PRECISION_MILLISECOND:
		return time.Unix(ts/1000, (ts%1000)*int64(time.Millisecond)).UTC()
	case TIME_PRECISION_MICROSECOND:
		return time.Unix(ts/1000000, (ts%1000000)*int64(time.Microsecond)).UTC()
	case TIME_PRECISION_NANOSECOND:
		return time.Unix(0, ts).UTC()
	default:
		fmt.Println("未知的精度，以秒级精度返回 time.Time")
		return time.Unix(ts, 0).UTC()
	}
}

// StringToLocalTime 字符串转换为本地时间
func StringToLocalTime(timeStr string) (time.Time, error) {
	layouts := []string{
		time.Layout,
		time.RFC822,
		time.RFC822Z,
		time.RFC850,
		time.RFC1123,
		time.RFC1123Z,
		time.RFC3339,
		time.RFC3339Nano,
		time.Kitchen,
		time.Stamp,
		time.StampMilli,
		time.StampMicro,
		time.StampNano,
		time.DateTime,
		time.DateOnly,
		time.TimeOnly,
	}
	utcTime := time.Now()
	var err error
	for _, layout := range layouts {
		utcTime, err = time.Parse(layout, timeStr)
		if err == nil {
			break
		}
	}
	if err != nil {
		return utcTime, err
	}
	// 传入的字符串转换为时间后一定是UTC时区的
	// 需要加上时区的偏移量生成新的UTC时间
	// 再将新的UTC时间转换为本地时间的时间

	// 获取当前时刻
	now := time.Now()

	// 通过当前时刻获取时区的名称和偏移量（秒）
	_, offset := now.Zone()

	// 将偏移量转换为小时数，注意偏移量是以秒为单位的
	offsetHours := offset / 3600
	offsetHours = -offsetHours
	return utcTime.Add(time.Duration(offsetHours) * time.Hour).Local(), nil
}

// SecondsToHuman 将秒转换为天、小时、分钟和秒的字符串
func SecondsToHuman(input int64) string {
	var result strings.Builder

	// 定义时间单位的秒数
	const (
		dayInSeconds    = 60 * 60 * 24
		hourInSeconds   = 60 * 60
		minuteInSeconds = 60
	)

	// 计算天、小时、分钟和秒
	days := input / dayInSeconds
	hours := (input % dayInSeconds) / hourInSeconds
	minutes := (input % hourInSeconds) / minuteInSeconds
	seconds := input % minuteInSeconds

	// 根据条件构建字符串
	if days > 0 {
		result.WriteString(fmt.Sprintf("%d天", days))
	}
	if hours > 0 || days > 0 { // 如果有天数，即使小时为0也显示
		result.WriteString(fmt.Sprintf("%d小时", hours))
	}
	if minutes > 0 || hours > 0 || days > 0 { // 如果有小时数或天数，即使分钟为0也显示
		result.WriteString(fmt.Sprintf("%d分", minutes))
	}
	result.WriteString(fmt.Sprintf("%d秒", seconds)) // 秒数总是显示

	return result.String()
}

// GetCurrentTimestampMinute 获取当前时间的整数分钟，返回Unix时间戳秒数
func GetCurrentTimestampMinute() int64 {
	currentTime := time.Now()
	result := currentTime.Unix() / 60 // 将当前时间的Unix时间戳秒数除以60得到整数分钟数
	// 再将分钟数乘以60得到整数分钟的Unix时间戳秒数
	result *= 60
	return result
}
